#include<iostream>
#include <cmath>
using namespace std;
// 需求：计算不同图形的面积和周长

// 比较抽象实体
// 抽象类: 将包含纯虚函数的类称为抽象类
// 抽象类是一定要被继承的，而且在子类中必须要对抽象类中所有的虚函数进行重写
class Shape
{
public:
    // 纯虚函数
    // 在抽象类中将后序子类中的一些接口规范好了
    virtual double GetArea() = 0;
    virtual double GetCircumference() = 0;
    /*{
        cout << "GetCircumference()=0" << endl;
    }*/
};

// Rect是具体的形状
class Rect : public Shape
{
public:
    Rect(double length, double width)
            : _length(length)
            , _width(width)
    {}

    double GetArea()
    {
        return _length * _width;
    }

    double GetCircumference()
    {
    	return 2 * (_length + _width);
    }
protected:
    double _length;
    double _width;
};

// Circle:是具体的形状
class Circle:public Shape
{
public:
    Circle(double r)
            : _r(r)
    {}

    double GetArea()
    {
        return PI*_r*_r;
    }

    double GetCircumference()
    {
        return 2 * PI*_r;
    }
protected:
    double _r;
    const double PI = 3.14;
};

// Triangle:是具体的形状
class  Triangle : public Shape
{
public:
    Triangle(double a, double b)
            : _a(a)
            , _b(b)
    {}

    double GetArea()
    {
        return _a*_b / 2;
    }

    double GetCircumference()
    {
        return _a + _b + sqrt(_a*_a + _b*_b);
    }

protected:
    double _a;
    double _b;
};


// D 也是一个抽象类
class D : public Shape
{
public:
    virtual double GetArea()
    {
        return 0.0;
    }

    // virtula double GetCircumference() = 0;
};


// 注意：抽象类不能直接实例化对象，但是抽象类也是类，类就是一个类型，可以创建抽象类的指针或者引用
void TestShape(Shape* ps)
{
    cout<<ps->GetArea()<<endl;
    cout << ps->GetCircumference() << endl;
}

int main()
{
    // Shape s;  // 编译失败：抽象类不能实例化对象--原因：Shape不是什么具体的图形，无法创建该种图形的对象

    // D d;

    Rect r(1, 2);
    Circle c(2);
    Triangle t(3,4);

    TestShape(&r);
    TestShape(&c);
    TestShape(&t);
    return 0;
}